using System;
using System.Security.Cryptography;
using System.Text;
using Newtonsoft.Json;
using UnityEngine;

namespace JH
{
    /// <summary>
    ///  有道词典文本翻译上传请求
    ///  https://ai.youdao.com/DOCSIRMA/html/trans/api/wbfy/index.html#section-9
    /// </summary>
    public class TextTranslationUpload
    {
        /// <summary>
        /// 待翻译文本，必须是UTF-8编码
        /// </summary>
        [JsonProperty("q")]
        public string Q { get; set; }

        /// <summary>
        /// 源语言，可设置为'auto'进行自动检测
        /// </summary>
        [JsonProperty("from")]
        public string From { get; set; }

        /// <summary>
        /// 目标语言
        /// </summary>
        [JsonProperty("to")]
        public string To { get; set; }

        /// <summary>
        /// 应用ID，可在应用管理中查看
        /// </summary>
        [JsonProperty("appKey")]
        public string AppKey { get; set; }

        /// <summary>
        /// 随机字符串，推荐使用UUID
        /// </summary>
        [JsonProperty("salt")]
        public string Salt = Guid.NewGuid().ToString();

        /// <summary>
        /// 签名不再是一个简单的属性，它现在是从其他值动态生成的
        /// </summary>
        [JsonProperty("sign")]
        public string Sign => GenerateSign();

        /// <summary>
        /// 签名类型，固定为'v3'
        /// </summary>
        [JsonProperty("signType")]
        public string SignType { get; set; } = "v3";

        /// <summary>
        /// 当前UTC时间戳(秒)
        /// </summary>
        [JsonProperty("curtime")]
        public string CurTime => DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
        
        /// <summary>
        /// 领域化翻译（可选），默认为general
        /// </summary>
        [JsonProperty("domain")]
        public string Domain { get; set; } = "general";

        /// <summary>
        /// 拒绝领域化翻译降级（可选），当领域化翻译失败时不改为通用翻译
        /// </summary>
        [JsonProperty("rejectDomain")]
        public bool RejectFallback { get; set; } = false;

        /// <summary>
        /// 应用密钥
        /// </summary>
        private readonly string _appSecret;
        
        public TextTranslationUpload(string q, string appKey, string appSecret, string from = "auto",
            string to = "zh-CHS")
        {
            _appSecret = appSecret ?? throw new ArgumentNullException(nameof(appSecret));

            Q = q ?? throw new ArgumentNullException(nameof(q));
            AppKey = appKey ?? throw new ArgumentNullException(nameof(appKey));
            From = from ?? throw new ArgumentNullException(nameof(from));
            To = to ?? throw new ArgumentNullException(nameof(to));
        }

        private string GenerateInput()
        {
            if (Q.Length <= 20)
                return Q;

            return Q.Substring(0, 10) + Q.Length + Q.Substring(Q.Length - 10);
        }

        private string GenerateSign()
        {
            // 生成 input 值
            string input = GenerateInput();

            // 使用 SHA256 创建散列
            using (SHA256 sha256Hash = SHA256.Create())
            {
                // 计算散列值
                byte[] data =
                    sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(AppKey + input + Salt + CurTime + _appSecret));

                // 使用 StringBuilder 来生成十六进制字符串
                StringBuilder builder = new StringBuilder();

                // 将每个字节转换为十六进制格式并添加到 StringBuilder
                for (int i = 0; i < data.Length; i++)
                {
                    //x2 表示十六进制小写两位 比如 0f 0a ... 
                    builder.Append(data[i].ToString("x2"));
                }

                // 返回十六进制字符串
                return builder.ToString();
            }
        }

        public WWWForm GetWWWForm()
        {
            WWWForm form = new WWWForm();

            // 必备参数
            form.AddField("q",  Q, Encoding.UTF8);
            form.AddField("from", From);
            form.AddField("to", To);
            form.AddField("appKey", AppKey);
            form.AddField("salt", Salt);
            form.AddField("sign", Sign);
            form.AddField("signType", SignType);
            form.AddField("curtime", CurTime);

            // 可选参数
            form.AddField("domain", Domain);
            form.AddField("rejectDomain", RejectFallback ? "1" : "0");

            return form;
        }
    }
}